#include "include/gtest.h"
#include "../Tool/include/TcpClient.h"
#include "../Tool/include/Variant.h"
#include "../Tool/include/ILogger.h"
#include "../Tool/include/ThreadPool.h"
#include "../Tool/include/Timer.h"
#include <thread>
#include <chrono>
#include <atomic>
#include <iostream>

using namespace Tool;
class ClientListener : public ITcpListener
{
public:
    TcpClient* client;

    ClientListener() : client(new TcpClient(this)) {}
    ~ClientListener() { delete client; }

    void OnConnect(const char* pAddress, uint16_t nPort) override
    {
        LOG_INFO("[Client] 连接服务器成功: %s:%d", pAddress, nPort);
    }

    void OnDisconnect(const char* pAddress, uint16_t nPort) override
    {
        LOG_INFO("[Client] 与服务器断开: %s:%d", pAddress, nPort);
    }

    void OnReceive(const char* pAddress, uint16_t nPort, const void* pBuffer, size_t nLength) override
    {
        // std::string data((const char*)pBuffer, nLength);
        // LOG_INFO("[Client] 收到服务器回复: %s",data.c_str());

        std::vector<uint8_t> binaryStr(static_cast<const uint8_t*>(pBuffer),static_cast<const uint8_t*>(pBuffer) + nLength);
        Variant variant;
        variant.FromBinaryString(binaryStr);
        LOG_INFO("[client] 收到数据: (%s:%d) :%s", pAddress, nPort, variant.ToJsonString().c_str());
    }

    void OnNotify(const char* pAddress, uint16_t nPort, const char* pMsg) override
    {
        LOG_INFO("[Client] 通知: (%s:%d) :%s", pAddress, nPort, pMsg);
    }
};

TEST(TcpClient, TcpClientInteraction)
{
    return;
    std::thread server_thread([](){
        ClientListener clientListener;
        clientListener.client->Start();
        bool connected = clientListener.client->Connect("192.168.1.11", 5090);
        std::string input;
        if (connected)
        {
            Variant maps;
            for(int i = 0; i < 1; ++i)
            {
                Variant map;
                map["code"] = "1000";
                map["value"] = i;
                map["msg"] = "This is a test message.";
                maps[std::to_string(i)] = map;
            }
            while (true)
            {
                std::getline(std::cin, input);
                if (input == "exit")
                {
                    break;
                }
                else if (input == "c")
                {
                    clientListener.client->Connect("192.168.1.11", 5090);
                }
                else if (input == "s")
                {
                    clientListener.client->Start();
                }
                else if (input == "d")
                {
                    clientListener.client->Stop();
                }
                else if (input == "send")
                {
                    Variant variant;
                    variant["code"] = "1001";
                    // variant["value"] = maps;
                    for(int i = 0; i < 10000; ++i)
                    {
                        std::string key = std::to_string(i);
                        variant["code" + key] = "1000";
                        variant["value" + key] = i;
                    }
                    const std::vector<uint8_t> &data = variant.ToBinaryString();
                    clientListener.client->Send(data.data(), data.size());
                }
                else
                {
                    Variant variant;
                    variant["code"] = "1000";
                    variant["value"] = input;
                    const std::vector<uint8_t> &data = variant.ToBinaryString();
                    clientListener.client->Send(data.data(), data.size());
                    // clientListener.client->Send(input.data(), input.size());
                }
            }
        }
        clientListener.client->Stop();
    });
    server_thread.join();
}

TEST(TcpClient, TcpClientTest)
{
    int count = 5000;
    ThreadPool pool(16);
    std::vector<ClientListener*> clients;
    clients.reserve(count);
    std::ifstream file("./aa.7z", std::ios::binary);
    std::vector<uint8_t> fileData((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());

    for (int i = 0; i < count; ++i)
    {
        pool.PostTask([&]() {
            ClientListener *clientListener = new ClientListener();
            clientListener->client->Start();
            bool connected = clientListener->client->Connect("192.168.101.217", 5090);
            if (!connected)
            {
                delete clientListener;
                LOG_ERROR("连接服务器失败！");
                return;
            }
            Variant map;
            map["code"] = 404;
            map["value"] = i;
            map["msg"] = "This is a test message.";
            // map["file"] = fileData;
            const std::vector<uint8_t>& data = map.ToBinaryString();
            bool result = clientListener->client->Send(data.data(), data.size());
            if (!result)
            {
                LOG_ERROR("发送数据失败！");
            }
            clients.push_back(clientListener);
        });
        Timer::SleepMs(1);
    }
    pool.WaitAll();
    Timer::SleepMs(2000);

    for (auto& client : clients)
    {
        if (client && client->client)
        {
            client->client->Stop();
            delete client;
        }
    }
    clients.clear();
}